using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class PlayerCharacter : MonoBehaviour{

	//aqui são as variaveis importantes (publicas)
	public int level;
	public enum Class{
		warrior = 0,
		rogue = 1,
		mage = 2
	}
	public Class classe;
	public enum Element{
		fire,
		water,
		air,
		earth
	}
	public Element element;

	[System.Serializable]
	public class Stat{
		public int current;
		public int max;
	}

	public Stat exp;
	public int str;
	public int agi;
	public int mag;
	public int vit;
	public Stat hp;
	public int attack;
	public int defense;
	public float critChance;
	public float critMult = 2;
	public float attackRange = 1.5f;

	//aqui é o resto, auxiliares (privadas)
	private static Dictionary<string, Class> dictClass = new Dictionary<string, Class> {
        { "warrior", Class.warrior },
        { "rogue", Class.rogue },
        { "mage", Class.mage }
    };
	private static Dictionary<string, Element> dictElement = new Dictionary<string, Element> {
        { "fire", Element.fire },
        { "water", Element.water },
        { "air", Element.air },
        { "earth", Element.earth }
	};
	private bool isAttacking;
	private string[] sqlData = new string[8];
	
	private PlayerController playerController;

	public enum damageState{
		miss,
		avoid,
		block,
		resist,
		hit,
		criticalHit
	}

	[System.Serializable]
	public class AttackOutput : object{
		protected int damage;
		protected damageState attackResult;
		public AttackOutput(int damage, damageState attackResult){
			this.damage = damage;
			this.attackResult = attackResult;
		}
	}

	void Start(){
		playerController = GetComponent<PlayerController>();
		playerController.attackRange.GetComponent<SphereCollider>().radius = attackRange;
	}

	[RPC]
	public void Assign(string info){
		if(info != ""){
			sqlData = info.Split(' ');
			level = Convert.ToInt32(sqlData[0]);
			classe = dictClass[sqlData[1]];
			element = dictElement[sqlData[2]];
			exp.current = Convert.ToInt32(sqlData[3]);
			str = Convert.ToInt32(sqlData[4]);
			agi = Convert.ToInt32(sqlData[5]);
			mag = Convert.ToInt32(sqlData[6]);
			vit = Convert.ToInt32(sqlData[7]);
			updateStats();
			PlayerPrefs.SetString("Player", info);
		}
	}

	void updateStats(){
		hp.max = vit * ((classe == Class.warrior) ? 30 : 20) + level * 50;
		hp.current = hp.max;
		attack = mainStat() * 3 + level * 2;
		defense = mainStat() * 2 + level;
	}

	void Update(){
		if(Input.GetKeyDown(KeyCode.F1)){ //salvar dados do jogador
			level = 5;
			classe = Class.mage;
			element = Element.earth;
			exp.current = 1;
			str = 20;
			agi = 10;
			mag = 5;
			vit = 10;
			updateStats();
			string info = level.ToString() + " " + classe.ToString() + " " + element.ToString() + " " +
				exp.current.ToString() + " " + str.ToString() + " " + agi.ToString() + " " + mag.ToString() + " " +
				vit.ToString();
			print(info);
			PlayerPrefs.SetString("Player", info);
			print("Dados salvos com sucesso!");
		}
		if(Input.GetKeyDown(KeyCode.F2)){ //mostra HP
			print("HP: " + hp.current + "/" + hp.max);
		}
		if(Input.GetKeyDown(KeyCode.F3)){ //atacar voce
			Attack(this);
		}
		if(Input.GetKeyDown(KeyCode.F4)){ //tomar dano
			Hit(attack);
		}
		if(Input.GetMouseButtonDown(0)){ //atacar inimigo
			
		}
	}

	public int mainStat(){
		if(classe == Class.warrior)
			return str;
		else if(classe == Class.rogue)
			return agi;
		else if(classe == Class.mage)
			return mag;
		else
			return 0;
	}

	public AttackOutput Attack(PlayerCharacter defender){
		int multiplyer = 1;
		int damage;
		damageState damageCase;
		int roll = UnityEngine.Random.Range(1, 100);
		Debug.Log("Roll: " + roll);
		if(roll <= critChance){
			damageCase = damageState.criticalHit;
			multiplyer = Mathf.RoundToInt(critMult);
		} else{
			damageCase = damageState.hit;
		}
		damage = attack * multiplyer;
		roll = UnityEngine.Random.Range(-20, 20);
		damage = Mathf.RoundToInt(damage + damage * roll / 100);
		print("Dano: " + damage);
		defender.hp.current -= damage;
		return new AttackOutput(damage, damageCase);
	}

	public void Hit(int attackDamage){
		int damage;
		int roll = UnityEngine.Random.Range(1, 21);
		print("Roll: " + roll);
		damage = Mathf.RoundToInt((attackDamage - defense) * ((roll == 20) ? 2 : 1) * (1 + UnityEngine.Random.Range(-20, 20) / 100));
		print("Dano: " + damage);
		hp.current -= damage;
	}
}